package com.simpou.commons.persistence.dao;

import com.simpou.commons.model.entity.BaseEntity;
import com.simpou.commons.model.entity.IdentifiableEntity;
import com.simpou.commons.utils.pagination.PageLimits;

import java.io.Serializable;
import java.util.List;


/**
 * Define o padrão Data Access Object para persistência básica de objetos.
 * Checagem de tipos é feita em runtime.
 *
 * @author Jonas Pereira
 * @version 2013-06-01
 * @since 2012-09-29
 */
public interface BasicDAO extends BaseDao {
    /**
     * Obtém uma entidade persistida que seja unicamente identificável.
     *
     * @param clasz Classe da entidade desejada.
     * @param id    Identificador único da entidade desejada.
     * @return Entidade determinada pelo identificador único.
     * @throws Exception Se houver.
     */
    public <T extends IdentifiableEntity<?>> T getSingle(final Class<T> clasz,
                                                         final Serializable id) throws Exception;

    /**
     * Remove uma entidade persistida.
     *
     * @param clasz Classe da entidade a ser removida.
     * @param id    Identificador único da entidade a ser removida.
     * @throws Exception Se houver.
     */
    public <T extends IdentifiableEntity<?>> void delete(final Class<T> clasz,
                                                         final Serializable id) throws Exception;

    /**
     * Persiste uma nova entidade.
     *
     * @param entity Nova entidade a ser persistida.
     * @return Entidade criada.
     * @throws Exception Se houver.
     */
    public <T extends BaseEntity> T create(final T entity)
            throws Exception;

    /**
     * Atualiza uma entidade já persistida.
     *
     * @param entity Entidade a ser atualizada.
     * @return Entidade atualizada.
     * @throws Exception Se houver.
     */
    public <T extends BaseEntity> T update(final T entity)
            throws Exception;

    /**
     * Remove uma entidade persistida.
     *
     * @param entity Entidade a ser removida.
     * @throws Exception Se houver.
     */
    public void delete(final BaseEntity entity) throws Exception;

    /**
     * Obtém lista completa das entidades persistidas de um determinado tipo.
     *
     * @param clasz Classe dos objetos desejados.
     * @return Lista de todos objetos persistidos do tipo especificado.
     * @throws Exception Se houver.
     */
    public <T extends BaseEntity> List<T> getList(final Class<T> clasz)
            throws Exception;

    /**
     * Realiza a contagem das entidades persistidas de um determinado tipo.
     *
     * @param clasz Classe das entidades a serem contadas.
     * @return Quantidade total das entidades persistidas do tipo especificado.
     * @throws Exception Se houver.
     */
    public <T extends BaseEntity> Long count(final Class<T> clasz)
            throws Exception;

    /**
     * Remove todos objetos do contexto de persistência atual.
     *
     * @throws java.lang.Exception Se houver alguma.
     */
    public <T extends BaseEntity> void deleteAll(final Class<T> clasz)
            throws Exception;

    /**
     * Obtém lista paginada das entidades persistidas de um determinado tipo.
     *
     * @param limits Paginação.
     * @param clasz  Classe das entidades desejadas.
     * @return Lista paginada das entidades persistidas do tipo especificado.
     * @throws Exception Se houver.
     */
    public <T extends BaseEntity> List<T> getList(final Class<T> clasz,
                                                  final PageLimits limits) throws Exception;

    /**
     * Recarrega os dados da entidade em memória. Útil em casos em que os dados da entidade foram atualizados
     * via outras entidades ou operações não relacionadas diretamente com ela.
     *
     * @param entity Entidade
     * @throws Exception Se houver.
     */
    public void refresh(BaseEntity entity) throws Exception;
}
